import pandas as pd
import numpy as np

print("***"*50)

# 定义一个numpy的二维数组
np_arr = np.random.randint(1, 100, (5,5))
print(np_arr)

# 转换numpy数组到pandas二维数组
pd_arr = pd.DataFrame(np_arr)
print(pd_arr)

print("***"*50)

# 带默认索引值的series
s1 = pd.Series([15, 25, 45])
print(s1)

# 带指定索引值的series
s2 = pd.Series([15, 25, 45], index=['手套', '围巾', '帽子'])
print(s2)
# 用字典创建series
dic = {"手套": 130, "围巾": 140, "帽子": 180}
s3 = pd.Series(dic)
print(s3)

# 获取series的所有值
print(s3.values)
# 获取series的所有索引
print(s3.index)
# 根据索引获取值
print(s3[1:3].values)

# 获取索引获取索引值和数据
print(s3[1:3])      #[围巾,帽子]

# 根据索引值获取值
print(s3["围巾"])     #140
print(s3.围巾)

print("***"*50)

# 通过列表创建dataframe
data =[[1, 2, 3, 4],[5, 6, 7, 8]]
df1 = pd.DataFrame(data)

# 通过字典创建dataframe
data = {
        'class': [1, 2, 3, 4],
        'people': [16, 15, 17, 18]
}
df2 = pd.DataFrame(data)
print(df2)

# 通过numpy数组创建dataframe
data = np.arange(8).reshape(2, 4)   #分配八个元素，且满足2行4列
df3 = pd.DataFrame(data)
print(df3)

print("***"*50)

# 创建自定义行和列索引值的dataframe
# 创建numpy二维数组
data = np.random.randint(100, 200, (2,4))
# 定义行索引列表和列索引列表
product_code = ['帽子', '围巾']
sales_date = ['一月','二月', '三月', '四月']
# 给DataFrame方法同时传入numpy数组和行索引列表和列索引列表
df3 = pd.DataFrame(data, index=product_code, columns=sales_date)
print(df3)


print(df3.shape)	#获取行列总数，shape[0]和[1]为行和列
print(df3.values)#获取值
print(df3.index)	 #获取行索引
print(df3.columns)#获取列索引
print(df3.axes)	#获取行索引和列索引
print(df3.T)	#获取转置后的dataframe
print(df3.dtypes)#获取数据类型

print("***"*50)

# 定义一个numpy的二维数组
np_arr = np.random.randint(1, 100, (5,5))
# 创建行索引列表，长度与数组行数一致
product_code =['商品'+ str(i) for i in range(np_arr.shape[0])]
# 生成一个日期列表，长度与数组列一致，periods参数：天数；freq参数： D表示普通日，B表示仅工作日
sale_date = pd.date_range('2024-01-01', periods=np_arr.shape[1],freq='D')
# 传入index行索引的同时用columns参数传入列索引
data = pd.DataFrame(np_arr, index=product_code, columns=sale_date )
print(data)

print("***"*50)

data =[[1, 2, 3, 4],[5, 6, 7, 8],[9,10,11,12],[13,14,15,16],[17,18,19,20]]
np_data = np.array(data)
arr1 = ["行号"+str(i) for i in range(np_data.shape[0])]
arr2 = ["商品"+str(i) for i in range(np_data.shape[1])]
df1 = pd.DataFrame(np_data,index=arr1,columns=arr2)

print(df1)

print("----"*20)

# 获取指定列的数据
print(df1.商品1) #使用点语法
print(df1['商品1']) # 使用方括号语法

print("----"*20)

#获取指定行的数据
print(df1[0:2])         #用索引的方式
print(df1.loc['行号0']) # 用标签的方式

print("----"*20)

# 获取行和列的数据
#指定行和列
print(df1.loc["行号2",["商品2","商品3"]])

#全部行和指定列
print(df1.loc[:,["商品2","商品3"]])

#全部列和指定行
print(df1.loc[["行号3","行号1"],:])

print("----"*20)

print("===="*10)
print(df1.loc["行号1",["商品2"]])
print("===="*10)
print(df1.loc[["行号1"],["商品2"]])
print("===="*10)
print(df1.loc[["行号1"],"商品2"])
print("===="*10)
print(df1.loc["行号1","商品2"])
print("===="*10)

print("------"*20)

# 用位置的方式
print(df1)
print("===="*10)
print(df1.iloc[2:4,1:3])
print("===="*10)
print(df1.iloc[2:4])
print("===="*10)
print(df1.iloc[:,1:3])

print("===="*10)
print(df1.商品3.values[2])                #series一维数组
# 获取指定条件的数据,默认显示所有列
# 单个条件
print(df1[df1.商品3>10])
print("===="*10)
# 多个条件，连接符：&并且，|或者
print(df1[(df1.商品3 >= 10) & (df1.商品1 <= 10)] )

print("===="*10)
# 设置条件并指定显示的列
print(df1[df1.商品3 > 10]['商品3'])

print("------"*20)

data = np.arange(12).reshape(3,4)
product = ['商品1', '商品3', '商品2']
year = ['2020', '2019', '2021', '2018']
df6 = pd.DataFrame(data,index=product,columns=year)
print(df6)

print("===="*10)

# 对整个表格排序
print(df6.sort_index(axis=0))           # 按行索引排序
print(df6.sort_index(axis=1))          # 按列索引排序
print("===="*10)
print(df6.sort_values(["2018"],ascending=True))                # 按列值排序
print(df6.sort_values(["2018"],ascending=False))

print("===="*10)

# 获取指定列并排序
print(df6['2018'].sort_values(ascending=False))
# 获取指定列并按行索引排序
print(df6['2018'].sort_index(ascending=False))

print("------"*20)

data =[[1, 2, 3, 4],[5, 6, 7, 8],[9,10,11,12],[13,14,15,16],[17,18,19,20]]
np_data = np.array(data)
arr1 = ["行号"+str(i) for i in range(np_data.shape[0])]
arr2 = ["商品"+str(i) for i in range(np_data.shape[1])]
df1 = pd.DataFrame(np_data,index=arr1,columns=arr2)

print(df1)
print("===="*10)

# 修改原有数据
df1.iloc[1,2] = 100             # 根据位置修改

df1.loc["行号2","商品0"] = 200              # 根据标签修改

#df1.loc[df1["商品3"] > 10, :] = 0           # 根据条件修改整行数据

df1.loc[df1["商品3"] == 12,"商品1"] = 300            # 根据条件修改指定列

print(df1)

print("------"*20)

# 插入行、列
# 直接指定新列
lst = ['1', '2', '3', '4', '5']

df1["商品5"] = pd.Series(lst,index=arr1)

# 追加行
s = pd.Series([1, 2, 3, 4, 5],index=df1.keys())
s.name = "行号5"
df2 = df1._append(s)    # append方法不会修改原数据

# 在指定位置插入一个新的列
df1.insert(1,'商品X',[199,299,399,499,599])
print(df2)

print("===="*10)
print(df1)

# 删除行和列，drop方法不修改原数据，axis为0表示行，1表示列
df2 = df1.drop('行号4', axis=0) # 删除行
print(df2)
df2 = df1.drop('商品1', axis=1)   # 删除列
print(df2)

print("------"*20)

# 创建一个DataFrame
lst = [[1, 2, 3],
       [4, 5, 6]]
df = pd.DataFrame(lst, index=['r1', 'r2'], columns=['c1', 'c2', 'c3'])
print(df)
print("===="*10)

# 与常数进行计算,每个都加2
print(df+2)
print(df.add(2))

print("===="*10)
#与列表进行计算，注意行列长度要一致（与表格长度一致，对应相加）
print(df.add([1, 2], axis=0))#按行加,
print(df.add([1, 2, 3], axis=1))#按列加

print("===="*10)
# 与DataFrame进行计算,仅计算相同索引的元素，不同索引的元素用NaN填充
df1 = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]],columns=['a', 'b', 'c'], index=['r1', 'r2', 'r3'])
df2 = pd.DataFrame([[0, 0], [-1, -1]], columns=['b', 'd'], index=['r2', 'r3'])
print(df1)
print("===="*10)
print(df2)
print(df1+df2)

print("------"*20)
# 创建一个模拟的公司销售数据集
sales_data = {
        '销售人员': ['张三', '李四', '王五', '张三', '赵六', '李四', '王五', '孙七'],
        '销售区域': ['北区', '南区', '东区', '北区', '西区', '南区', '东区', '北区'],
        '销售产品': ['产品A', '产品B', '产品A', '产品C', '产品B', '产品A', '产品C', '产品B'],
        '销售额': [1500, 2000, 1200, 1800, 2500, 1000, 1600, 2200]
}
# 将数据转换为DataFrame
df = pd.DataFrame(sales_data)
print("原始销售数据：")
print(df)
# 按销售区域分组，并计算销售总额，reset_index方法重新设置行索引
df1 = df.groupby("销售区域")["销售额"].sum().reset_index()
df1.columns = ["销售区域","销售总额"]           #列的重命名
print("\n按销售区域分组后的销售总额：")
print(df1)

print("===="*10)
# 按销售区域和销售人员分组，并计算销售总额
df2 = df.groupby(["销售区域","销售人员"])["销售额"].sum().reset_index()
df2.columns = ["销售区域","销售人员","销售总额"]
print("\n按销售区域和销售产品分组后的销售总额：")
print(df2)

print("------"*20)

# 创建三个dataframe用于合并
columns = ['列1', '列2', '列3', '列4']
df1 = pd.DataFrame(np.arange(12).reshape((3,4)),columns=columns)
df2 = pd.DataFrame(np.arange(12,24).reshape((3,4)),columns=columns)
df3 = pd.DataFrame(np.arange(24,36).reshape((3,4)),columns=columns)
print(df1)
print("===="*10)
print(df2)
print("===="*10)
print(df3)
print("===="*10)
#纵向合并,可以用ignore_index=True生成新的行索引
df4 = pd.concat([df1,df2,df3],axis=0)
print('---------------纵向合并结果---------------')
print(df4)

#横向合并
df5 = pd.concat([df1,df2,df3],axis=1)
print('---------------横向合并结果---------------')
print(df5)

print("------"*20)

# 创建两个dataframe用于合并，它们拥有两个相同的列key1和key2
A = pd.DataFrame({'key1':['K0','K0','K1','K2'],
                'key2':['K0','K1','K0','K1'],
                'A':['A0','A1','A2','A3'],
                'B':['B0','B1','B2','B3']})
B = pd.DataFrame({'key1':['K0','K1','K1','K3'],
                 'key2':['K0','K0','K0','K0'],
                'C':['C0','C1','C2','C3'],
                'D':['D0','D1','D2','D3']})
# 合并两个dataframe，how参数指定合并方式，默认是inner
# 设置参数indicator=True会生成_merge列，显示合并方式

print(A)
print("===="*10)
print(B)
print("===="*10)

res_1 = pd.merge(A,B,on=['key1','key2'],how='inner')
res_2 = pd.merge(A,B,on=['key1','key2'],how='outer')
res_3 = pd.merge(A,B,on=['key1','key2'],how='left')
res_4 = pd.merge(A,B,on=['key1','key2'],how='right')
print('-------------------------how的参数取inner的结果--------------------')
print(res_1)
print('-------------------------how的参数取outer的结果--------------------')
print(res_2)
print('-------------------------how的参数取left的结果---------------------')
print(res_3)
print('-------------------------how的参数取right的结果--------------------')
print(res_4)

print("------"*20)

# 创建示例数据
data = {'姓名': ['Alice', 'Bob', None, 'David'],
        '年龄': [24, None, 19, 33],
        '生日': ['invalid_date', '2023-01-02', np.nan, '2023-01-05'],
        '薪资': [50000, 60000, None, 58000]}
df = pd.DataFrame(data)
# 输出缺失值判断结果,可配合sum统计,对应有notnull方法
print(df.isnull())

print("===="*10)
# 使用均值填充缺失值
#df['姓名'] = df['姓名'].fillna('无')      #在原有的dataFrame中填充，填充“无”
df['年龄'] = df['年龄'].fillna(df['年龄'].mean())      #更具年龄的平均值填充
df['薪资'] = df['薪资'].fillna(df['薪资'].median())    #更具薪资的中位数填充

# 使用前一个值填充缺失值，method='bfill'用后一个值填充
df['姓名'] = df['姓名'].fillna(df['姓名'].bfill())       #使用前一个值填充，如果为第一个，则不填充
#df['生日'] = df['生日'].fillna(df['生日'].ffill())
print(df)

print("===="*10)

# 删除含有缺失值的行
df.dropna(inplace=True)
print(df)
# 删除含有缺失值的列
df.dropna(axis=1, inplace=True)
print(df)

print("------"*20)

# 创建包含重复值的示例数据
data = {'Name': ['Alice', 'Bob', 'Alice', 'David'],
         'Age': [24, 19, 24, 33]}
df = pd.DataFrame(data)
print(df)

# 查找重复值，也可以配合sum进行统计
duplicates = df.duplicated()
print(duplicates)

# 删除重复值
df.drop_duplicates(inplace=True)
print(df)

print("------"*20)

# 创建示例数据
data = {'Name': ['aliCe ', ' Bob', 'DAVID'],
        'Date': ['2024-11-01', '03/02/2024', '2024.04.03'],
        'Value': ['1.0', '2.5', '3.8']}
df = pd.DataFrame(data)


# 去除空白字符
df['Name'] = df['Name'].str.strip()
# 转换为小写
df['Name'] = df['Name'].str.lower()
# 将字符串转换为日期时间格式
df['Date'] = pd.to_datetime(df['Date'],format='mixed')
# 将字符串转换为浮点数，再转换为整数
df['Value'] = df['Value'].astype(float).astype(int)
print(df)
print(df.dtypes)# 查看数据类型

print("------"*20)

# 创建一个示例DataFrame
data = {
         'id': [1, 2, 3, 4, 5],
         '年龄': [25, 27, 29, 150, 32] # 注意这里的150是一个异常值
}
df = pd.DataFrame(data)
# 方式一：标识异常值为None后再替换 # 识别异常值：我们这里定义一个简单的规则，超过100的年龄被视为异常值
df['年龄'] = df['年龄'].apply(lambda x: x if x < 100 else None) # 替换异常值为None# 输出处理后的数据
print("\n处理后的数据:")
print(df)

# 可以选择使用均值/中位数填补缺失值
df['年龄'] = df['年龄'].fillna(df['年龄'].mean())     # 输出最终数据
print("\n最终数据:")
print(df)

# 方式二：直接替换异常值
df.loc[(df['年龄'] < 0) | (df['年龄'] > 100) , '年龄'] = 18
print(df)

print("------"*20)







































